package com.starrtc.demo.imclient.client;

import com.starrtc.demo.imclient.ClientSender.ChatSender;
import com.starrtc.demo.imclient.ClientSender.LoginSender;
import com.starrtc.demo.imclient.clientHandler.ChatMsgHandler;
import com.starrtc.demo.imclient.clientHandler.ExceptionHandler;
import com.starrtc.demo.imclient.clientHandler.LoginResponceHandler;
import com.starrtc.demo.imclient.iMcommon.bean.UserDTO;
import com.starrtc.demo.imclient.iMcommon.codec.ProtobufDecoder;
import com.starrtc.demo.imclient.iMcommon.codec.ProtobufEncoder;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.GenericFutureListener;

public class NettyClient {

    public static NettyClient instance;

    public static NettyClient getInstance(){
        if(instance == null){
            instance = new NettyClient();
            return instance;
        }
        return instance;
    }

    // 服务器ip地址
    private String host;
    // 服务器端口
    private int port;

    private Channel channel;
    private ChatSender sender;
    private LoginSender loginSender;

    /**
     * 唯一标记
     */
    private boolean initFalg = true;
    private UserDTO user;
    private GenericFutureListener<ChannelFuture> connectedListener;

    private Bootstrap b;
    private EventLoopGroup g;

    private NettyClient() {

        /**
         * 客户端的是Bootstrap，服务端的则是 ServerBootstrap。
         * 都是AbstractBootstrap的子类。
         **/

        /**
         * 通过nio方式来接收连接和处理连接
         */

        g = new NioEventLoopGroup();


    }

    /**
     * 重连
     */
    public void doConnect() {
        try {
            b = new Bootstrap();

            b.group(g);
            b.channel(NioSocketChannel.class);
            b.option(ChannelOption.SO_KEEPALIVE, true);
            b.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
            b.remoteAddress(host, port);

            // 设置通道初始化
            b.handler(
                    new ChannelInitializer<SocketChannel>() {
                        public void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast("decoder", new ProtobufDecoder());
                            ch.pipeline().addLast("encoder", new ProtobufEncoder());
                            ch.pipeline().addLast("loginResponseHandler",LoginResponceHandler.getInstance());
                            ch.pipeline().addLast("chatMsgHandler",ChatMsgHandler.getInstance());
                            ch.pipeline().addLast("exceptionHandler",ExceptionHandler.getInstance());
                        }
                    }
            );
//            log.info("客户端开始连接 [坤总 IM]");

            ChannelFuture f = b.connect();
            f.addListener(connectedListener);


            // 阻塞
            // f.channel().closeFuture().sync();

        } catch (Exception e) {
//            log.info("客户端连接失败!" + e.getMessage());
        }
    }

    public void close() {
        g.shutdownGracefully();
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public UserDTO getUser() {
        return user;
    }

    public void setUser(UserDTO user) {
        this.user = user;
    }

    public GenericFutureListener<ChannelFuture> getConnectedListener() {
        return connectedListener;
    }

    public void setConnectedListener(GenericFutureListener<ChannelFuture> connectedListener) {
        this.connectedListener = connectedListener;
    }
}
